package com.hadwinling.controller;

import com.hadwinling.entity.NuclearParam;
import com.hadwinling.service.IoTDBService;
import com.hadwinling.tool.Msg;
import org.apache.iotdb.rpc.IoTDBConnectionException;
import org.apache.iotdb.rpc.StatementExecutionException;
import org.apache.iotdb.session.SessionDataSet;
import org.apache.iotdb.tsfile.read.common.Field;
import org.apache.iotdb.tsfile.read.common.RowRecord;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @Classname IotDBController
 * @Description TODO
 * @Date 2021/7/3 16:09
 * @Created by
 */
@CrossOrigin()
@Controller
public class IotDBController {

    @Resource
    private IoTDBService iotdbService;

    @GetMapping("/")
    public String index() {
        return "index";
    }


    /**
     * http://localhost:8080/set/root.dc_dx1
     * 设置存储组
     *
     * @param storage
     * @return
     */
    @GetMapping("/set")
    public String setStorageGroup(@RequestParam(name = "storage") String storage) {
        System.out.println("开始创建：" + storage);
        iotdbService.setStorageGroup(storage);
        return "index";
    }

    /**
     * 删除存储组
     *
     * @param storage
     * @return
     */
    @GetMapping("/delete")
    public String deleteStorageGroup(@RequestParam(value = "storage") String storage) {
        System.out.println("开始删除：" + storage);
        iotdbService.deleteStorageGroup(storage);
        return "index";
    }

    /**
     * 用法 ：/insert/root.dc.dx01/52/6
     *
     * @param storage
     * @param zujianNum  组件的数量
     * @param zhibiaoNum 指标的数量 设备的数量
     * @return 花费时间
     */
    @PostMapping("/insert")
    @ResponseBody
    public String insert(@RequestParam(value = "storage") String storage,
                         @RequestParam(value = "zujianNum") int zujianNum,
                         @RequestParam(value = "zhibiaoNum") int zhibiaoNum) throws IOException {
        long start = System.currentTimeMillis();
        iotdbService.insert(storage, zujianNum, zhibiaoNum);
        long end = System.currentTimeMillis();
        System.out.println("花费：" + (end - start) + "豪秒");
        return "花费：" + (end - start) / 1000.0 + "秒";
    }

    /**
     * 2.1 plot_burn_ind_mod (burn,indicator,module)
     * 给定 燃耗步，指标，组件值；得层、时刻的变化（3D）
     *
     * @param nuclearParam
     * @return
     * @throws StatementExecutionException
     * @throws IoTDBConnectionException
     */
    @PostMapping("/plot_burn_indicator_module")
    @ResponseBody
    public Msg plot_burn_indicator_module(@RequestBody NuclearParam nuclearParam) throws StatementExecutionException, IoTDBConnectionException {
        Msg msg = new Msg();
        final SessionDataSet sessionDataSet = iotdbService.plot_burn_indicator_module(nuclearParam);
        if (sessionDataSet == null) {
            msg.setCode(100);
            msg.setMsg("出错了");
            return msg;
        }
        msg.setMsg("成功啦");
        msg.setCode(200);

        int timeNum = (nuclearParam.getBurn_end() - nuclearParam.getBurn_start() + 1) * 98;
        Float[][] value = new Float[timeNum][32];

        int row = 0;
        Float min = Float.MAX_VALUE;
        Float max = Float.MIN_VALUE;
        while (sessionDataSet.hasNext()) {
            final RowRecord next = sessionDataSet.next();
            final List<Field> fields = next.getFields();
            for (int j = 0; j < fields.size(); j++) {
                Field field = fields.get(j);
                float floatV = field.getFloatV();

                if (min > floatV) {
                    min = floatV;
                }
                if (max < floatV) {
                    max = floatV;
                }
                value[row][j] = floatV;
            }
            row++;
        }
        msg.add("Max", max);
        msg.add("Min", min);

        // 层数
        int[] layers = new int[32];
        for (int layer = 0; layer < 32; layer++) {
            layers[layer] = (layer + 1);
        }
        // 时刻数
        int[] times_num = new int[timeNum];
        for (int t = 0; t < timeNum; t++) {
            times_num[t] = (t + 1);
        }
        msg.add("layers", layers);
        msg.add("time", times_num);

        msg.add("value", value);
        return msg;
    }

    /**
     * 2.2 plot_act_burn_ind_mod
     *
     * @param nuclearParam
     * @return
     * @throws StatementExecutionException
     * @throws IoTDBConnectionException
     */
    @PostMapping("/plot_act_burn_ind_mod")
    @ResponseBody
    public Msg plot_act_burn_ind_mod(@RequestBody NuclearParam nuclearParam) throws StatementExecutionException, IoTDBConnectionException {
        Msg msg = new Msg();
        final SessionDataSet sessionDataSet = iotdbService.plot_act_burn_ind_mod(nuclearParam);
        if (sessionDataSet == null) {
            msg.setCode(100);
            msg.setMsg("出错啦");
            return msg;
        }
        msg.setCode(200);
        msg.setMsg("成功啦");
        Float min = Float.MAX_VALUE;
        Float max = Float.MIN_VALUE;

        int timeNum = (nuclearParam.getBurn_end() - nuclearParam.getBurn_start() + 1) * 98;
        int[] times_num = new int[timeNum];
        for (int t = 0; t < timeNum; t++) {
            times_num[t] = (t + 1);
        }
        msg.add("time", times_num);

        Float[] value = new Float[timeNum];
        int row = 0;
        while (sessionDataSet.hasNext()) {
            final RowRecord next = sessionDataSet.next();
//            System.out.println(next);
            final float floatV = next.getFields().get(0).getFloatV();

            if (min > floatV) {
                min = floatV;
            }
            if (max < floatV) {
                max = floatV;
            }
            value[row] = floatV;
            row++;
        }
        msg.add("Max", max);
        msg.add("min", min);


        msg.add("value", value);
        return msg;
    }


    /**
     * 2.3 plot_mod_ind_time(module,indicator,time)
     * #给定组件、指标、时刻, 得燃耗步、层 变化（3D图）
     *
     * @param nuclearParam 传过来的值
     * @return
     */
    @PostMapping("/plot_mod_ind_time")
    @ResponseBody
    public Msg plot_mod_ind_time(@RequestBody NuclearParam nuclearParam) throws StatementExecutionException, IoTDBConnectionException {
        Msg msg = new Msg();
        ArrayList<List<Field>> lists = null;

        try {
            lists = iotdbService.plot_mod_ind_time(nuclearParam);
        } catch (StatementExecutionException e) {
            e.printStackTrace();
            msg.setCode(100);
            msg.setMsg("出错了");
            return msg;
        } catch (IoTDBConnectionException e) {
            e.printStackTrace();
            msg.setCode(100);
            msg.setMsg("出错了");
            return msg;
        }

        if (lists == null) {
            msg.setCode(100);
            msg.setMsg("出错了");
            return msg;
        }
        msg.setCode(200);
        msg.setMsg("成功啦");

        Float min = Float.MAX_VALUE;
        Float max = Float.MIN_VALUE;

        Float[][] value = new Float[18][32];

        int row = 0;
        for (int i = 0; i < lists.size(); i++) {
            List<Field> fields = lists.get(i);
            for (int j = 0; j < fields.size(); j++) {
                Field field = fields.get(j);
                float floatV = field.getFloatV();

                if (min > floatV) {
                    min = floatV;
                }
                if (max < floatV) {
                    max = floatV;
                }
                value[row][j] = floatV;
            }
            row++;
        }

        msg.add("Max", max);
        msg.add("Min", min);

        // 燃耗步数
        int[] burns = new int[18];
        for (int burn = 0; burn < 18; burn++) {
            burns[burn] = (burn + 1);
        }
        // 层数
        int[] layers = new int[32];
        for (int t = 0; t < 32; t++) {
            layers[t] = (t + 1);
        }
        msg.add("layers", layers);
        msg.add("burns", burns);

        msg.add("value", value);
        return msg;
    }

    /**
     * 2.4 plot_mod_lay_ind
     * {module:3,indicator:2,layer:23}
     * #给定组件、层，指标，展示燃耗步、时刻、值的变化（3D图）
     *
     * @param nuclearParam 传过来的值
     * @return
     */
    @PostMapping("/plot_mod_lay_ind")
    @ResponseBody
    public Msg plot_mod_lay_ind(@RequestBody NuclearParam nuclearParam) throws StatementExecutionException, IoTDBConnectionException {
        Msg msg = new Msg();
        SessionDataSet sessionDataSet = iotdbService.plot_mod_lay_ind(nuclearParam);
        if (sessionDataSet == null) {
            msg.setCode(100);
            msg.setMsg("出错啦");
        }
        msg.setCode(200);
        msg.setMsg("成功啦");

        Float[][] value = new Float[18][98];

        Float min = Float.MAX_VALUE;
        Float max = Float.MIN_VALUE;

        while (sessionDataSet.hasNext()) {
            for (int i = 0; i < 18; i++) {
                for (int j = 0; j < 98; j++) {
                    final RowRecord next = sessionDataSet.next();
                    final List<Field> fields = next.getFields();

                    Field field = fields.get(0);
                    float floatV = field.getFloatV();

                    if (min > floatV) {
                        min = floatV;
                    }
                    if (max < floatV) {
                        max = floatV;
                    }
                    value[i][j] = floatV;
                }
            }
        }

        msg.add("Max", max);
        msg.add("Min", min);

        // 燃耗步数
        int[] burns = new int[18];
        for (int burn = 0; burn < 18; burn++) {
            burns[burn] = (burn+1);
        }
        // 时刻数
        int[] times_num = new int[98];
        for (int t = 0; t < 98; t++) {
            times_num[t] = (t+1);
        }
        msg.add("burns", burns);
        msg.add("time", times_num);

        msg.add("value", value);
        return msg;
    }

    /**
     * 2.5plot_mod_lay_ind_2d(module,layer,indicator)
     * #给定组件、层，指标，展示燃耗步、时刻、值的变化（2D图）
     *
     * @param nuclearParam
     * @return
     */
    @PostMapping("/plot_mod_lay_ind_2d")
    @ResponseBody
    public Msg plot_mod_lay_ind_2d(@RequestBody NuclearParam nuclearParam) throws StatementExecutionException, IoTDBConnectionException {
        Msg msg = new Msg();
        SessionDataSet sessionDataSet = iotdbService.plot_mod_lay_ind_2d(nuclearParam);
        if (sessionDataSet == null) {
            msg.setCode(100);
            msg.setMsg("出错啦");
        }
        msg.setCode(200);
        msg.setMsg("成功啦");

        Float[] value = new Float[1764];
        Float min = Float.MAX_VALUE;
        Float max = Float.MIN_VALUE;

        int row = 0;
        while (sessionDataSet.hasNext()) {
            final RowRecord next = sessionDataSet.next();

            final float floatV = next.getFields().get(0).getFloatV();

            if (min > floatV) {
                min = floatV;
            }
            if (max < floatV) {
                max = floatV;
            }

            value[row] = floatV;
            row++;
        }
        msg.add("Max", max);
        msg.add("Min", min);

        // 时刻数
        int[] times_num = new int[row];
        for (int t = 0; t < row; t++) {
            times_num[t] = (t+1);
        }
        msg.add("time", times_num);

        msg.add("value", value);

        return msg;
    }

    /**
     * 2.6plot_butn_ind_time(burn,indicator,time)
     * #给定燃耗步，指标，时刻，展示组件、层、值的变化（3D图）
     *
     * @param nuclearParam
     * @return
     */
    @PostMapping("/plot_butn_ind_time")
    @ResponseBody
    public Msg plot_butn_ind_time(@RequestBody NuclearParam nuclearParam) {
        Msg msg = new Msg();
        ArrayList<List<Field>> lists = null;
        try {
            lists = iotdbService.plot_butn_ind_time(nuclearParam);
        } catch (StatementExecutionException e) {
            e.printStackTrace();
            msg.setCode(100);
            msg.setMsg("出错啦");
            return msg;
        } catch (IoTDBConnectionException e) {
            e.printStackTrace();
            msg.setCode(100);
            msg.setMsg("出错啦");
            return msg;
        } catch (InterruptedException e) {
            e.printStackTrace();
            msg.setCode(100);
            msg.setMsg("出错啦");
            return msg;
        }
        if (lists == null) {
            msg.setCode(100);
            msg.setMsg("出错啦");
            return msg;
        }
        msg.setCode(200);
        msg.setMsg("成功啦");

        Float min = Float.MAX_VALUE;
        Float max = Float.MIN_VALUE;
        Float[][] value = new Float[52][32];

        for (int row = 0; row < 52; row++) {
            final List<Field> fields = lists.get(row);
            for (int col = 0; col < fields.size(); col++) {
                final float floatV = fields.get(col).getFloatV();
                if (min > floatV) {
                    min = floatV;
                }
                if (max < floatV) {
                    max = floatV;
                }
                value[row][col] = floatV;
            }
        }
        msg.add("Max", max);
        msg.add("Min", min);

        int[] module_nums = new int[52];
        for (int i = 0; i < 52; i++) {
            module_nums[i] = (i + 1);
        }
        msg.add("module", module_nums);

        // 层数
        int[] layers = new int[32];
        for (int t = 0; t < 32; t++) {
            layers[t] = (t+1);
        }
        msg.add("layers", layers);
        msg.add("value", value);

        return msg;
    }


    /**
     * 2.7 {"indicator":"1","burn_start":"1","burn_end":"5","module":"1","module_end":"5","time_start":"1","time_end":"5"}
     * #给定燃耗步，指标，展示时刻、组件、层、值的变化（3D四维图）
     *
     * @param nuclearParam
     * @return
     */
    @PostMapping("/plot_burn_ind")
    @ResponseBody
    public Msg plot_burn_ind(@RequestBody NuclearParam nuclearParam) throws StatementExecutionException, IoTDBConnectionException {
        Msg msg = new Msg();
        ArrayList<List<Field>> lists = null;
        try {
            lists = iotdbService.plot_burn_ind(nuclearParam);
        } catch (StatementExecutionException e) {
            e.printStackTrace();
            msg.setCode(100);
            msg.setMsg("出错啦");
            return msg;
        } catch (IoTDBConnectionException e) {
            e.printStackTrace();
            msg.setCode(100);
            msg.setMsg("出错啦");
            return msg;
        } catch (InterruptedException e) {
            e.printStackTrace();
            msg.setCode(100);
            msg.setMsg("出错啦");
            return msg;
        }
        if (lists == null) {
            msg.setCode(100);
            msg.setMsg("出错啦");
            return msg;
        }
        msg.setCode(200);
        msg.setMsg("成功啦");

        Float min = Float.MAX_VALUE;
        Float max = Float.MIN_VALUE;

        int time_nums = nuclearParam.getTime_end() - nuclearParam.getTime_start() + 1;
        int module_num = nuclearParam.getModule_end() - nuclearParam.getModule() + 1;

        Float[][][] value = new Float[time_nums][module_num][32];
        int row = 0;
        for (int i = 0; i < time_nums; i++) {
            for (int j = 0; j < module_num; j++) {
                final List<Field> fields = lists.get(row);
                for (int col = 0; col < fields.size(); col++) {
                    final float floatV = fields.get(col).getFloatV();
                    if (min > floatV) {
                        min = floatV;
                    }
                    if (max < floatV) {
                        max = floatV;
                    }
                    value[row][j][col] = floatV;
                }
            }
            row++;
        }

        msg.add("Max", max);
        msg.add("Min", min);

        // 时刻数
        int[] times_num = new int[time_nums];
        final int time_start = nuclearParam.getTime_start();
        final int module = nuclearParam.getModule();
        for (int t = 0; t < time_nums; t++) {
            times_num[t] = t + time_start;
        }
        msg.add("time", times_num);

        int[] module_nums = new int[module_num];
        for (int i = 0; i < module_num; i++) {
            module_nums[i] = i + module;
        }
        msg.add("module", module_nums);

        // 层数
        int[] layers = new int[32];
        for (int t = 0; t < 32; t++) {
            layers[t] = (t+1);
        }
        msg.add("layers", layers);

        msg.add("value", value);

        return msg;
    }

    @PostMapping("/plot_burn_time_indicator")
    @ResponseBody
    public Msg plot_burn_time_indicator(@RequestBody NuclearParam nuclearParam){
        Msg msg = new Msg();
        ArrayList<List<Field>> lists = null;
        try {
            lists= iotdbService.plot_burn_time_indicator(nuclearParam);
        } catch (StatementExecutionException e) {
            e.printStackTrace();
            e.printStackTrace();
            msg.setCode(100);
            msg.setMsg("出错啦");
        } catch (IoTDBConnectionException e) {
            e.printStackTrace();
            msg.setCode(100);
            msg.setMsg("出错啦");
        }
        if (lists == null){
            msg.setCode(100);
            msg.setMsg("出错啦");
        }
        msg.setCode(200);
        msg.setMsg("成功啦");

        Float min = Float.MAX_VALUE;
        Float max = Float.MIN_VALUE;

        Float[][] value = new Float[52][32];
        int row = 0 ;
        for (int i = 0 ; i < 52;i++){
            final List<Field> fields = lists.get(row);
            for (int col = 0; col < fields.size(); col++) {
                final float floatV = fields.get(col).getFloatV();
                if (min > floatV) {
                    min = floatV;
                }
                if (max < floatV) {
                    max = floatV;
                }
                value[row][col] = floatV;
            }
            row++;
        }

        msg.add("Max", max);
        msg.add("Min", min);

        int[] x = new int[8];
        int[] y = new int[8];
        for (int i = 0 ; i < 8 ; i++){
            x[i] = i+1;
            y[i] = i+1;
        }
        msg.add("x",x);
        msg.add("y",y);

        // 层数
        int[] layers = new int[32];
        for (int t = 0; t < 32; t++) {
            layers[t] = (t+1);
        }
        msg.add("layers", layers);

        msg.add("value", value);

        return msg;
    }

}
